<?php

class MimeMessage {
    protected $_to = array();
    protected $_cc = array();
    protected $_bcc = array();
    
    protected $_mime = '1.0';
    protected $_content_transfer_encoding = '8bit';
    protected $_charset = 'utf-8';
    protected $_from = '';
    protected $_replyTo = '';
    protected $_returnPath = '';
    protected $_xMailer = '';
    protected $_xPriority = 'Normal';
    protected $_priorities = array('Highest','High','Normal','Low','Lowest');
    
    protected $_subject = '';
    protected $_plainText  ='';
    protected $_html = '';
    
    protected $_headers = array();
    
    protected $_msgTo = '';
    protected $_msgSubject = '';
    protected $_msgContent = '';
    protected $_msgHeaders = '';
    
    protected $_attachments = array();
    
    protected $_boundary = '';
    protected $_boundaryA = '';
    protected $_boundaryR = '';
    protected $_boundaryM = '';
    
    public function __construct() {
        $this->_boundary = sha1(time());
        $this->_boundaryA = 'a-'.$this->_boundary;
        $this->_boundaryR = 'r-'.$this->_boundary;
        $this->_boundaryM = 'm-'.$this->_boundary;
    }
    
    public function msgTo($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            array_push($this->_to,$email);
        }
    }
    
    public function msgCc($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            array_push($this->_cc,$email);
        }
    }
    
    public function msgBcc($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            array_push($this->_bcc,$email);
        }
    }
    
    public function msgFrom($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            $this->_from = $email;
        }
    }
    
    public function msgReplyTo($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            $this->_replyTo = $email;
        }
    }
    
    public function msgReturnPath($email='',$name='') {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = trim($name);
            if (!empty($name)) {
                $email = $name.' <'.$email.'>';
            }
            $this->_returnPath = $email;
        }
    }
    
    public function msgXMailer($xMailer='') {
        $this->_xMailer = filter_var($xMailer,FILTER_SANITIZE_STRING);
    }
    
    public function msgXPriority($xPriority='') {
        $this->_xPriority = filter_var($xPriority,FILTER_SANITIZE_STRING);
    }
    
    public function msgPlainText($plainText='',$mode='append') {
        $mode = strtolower(trim($mode));
        if ($mode == 'clear') {
            $this->_plainText = '';
        }
        $this->_plainText .= $plainText;
    }
    
    public function msgHtml($html='',$mode='append') {
        $mode = strtolower(trim($mode));
        if ($mode == 'clear') {
            $this->_html = '';
        }
        $this->_html .= $html;
    }
    
    public function msgSubject($subject='',$mode='append') {
        $mode = strtolower(trim($mode));
        if ($mode == 'clear') {
            $this->_subject = '';
        }
        $this->_subject .= $subject;
    }
    
    public function msgAttachment($attachment='') {
        if (file_exists($attachment) && is_readable($attachment)) {
            array_push($this->_attachments,$attachment);
        }
    }
    
    private function _addEmail($container =null,$email='',$name='') {
        if (is_array($container)) {
            $email = $this->_email($email,$name);
            if ($email) {                
                if (!in_array($email,$container)) {
                    array_push($container,$email);
                }
            }
        }
    }
    
    private function _email($email,$name) {
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $name = filter_var($name,FILTER_SANITIZE_STRING);
//            if (!empty($name)) {
//                $email = $name.'<'.$email.'>';
//            }
        }
        return $email;
    }
    
    public function sendMessage() {
        $this->_prepMail();
        return mail($this->_msgTo,
                    $this->_msgSubject,
                    $this->_msgContent,
                    $this->_msgHeaders);
    }
    
    private function _prepMail() {
        $prep = true;
        $this->_msgTo = implode(',',$this->_to);
        $this->_msgSubject = $this->_subject;
        $this->_prepHeaders();
        $this->_prepMessage();
        $this->_msgHeaders = implode("\r\n",$this->_headers);
        return $prep;
    }
    
    private function _prepMessage() {
        $msgContent = array();
        
        if (count($this->_attachments)>0) {
            array_push($this->_headers,'Content-Type:multipart/mixed;boundary="'.$this->_boundaryM.'"');
            array_push($msgContent,'--'.$this->_boundaryM);
            array_push($msgContent,'Content-Type:multipart/alternative;boundary='.$this->_boundaryA);
            array_push($msgContent,$this->_prepAlternative());
            foreach($this->_attachments as $attachment) {
                array_push($msgContent,'--'.$this->_boundaryM);
                $attached = $this->_prepAttachment($attachment);
                array_push($msgContent,$attached);
            }
            array_push($msgContent,'--'.$this->_boundaryM.'--');
            $this->_msgContent = implode("\r\n",$msgContent);
        }
        else {
            array_push($this->_headers,'Content-Type:multipart/alternative;boundary="'.$this->_boundaryA.'"');
            $this->_msgContent = $this->_prepAlternative();
        }
    }
    
    private function _prepAttachment($attachment) {
        $msgAttachment = array();
        
        // php.ini enable extension=php_fileinfo.dll
        $fileName = basename($attachment);
        $fileInfo = finfo_open(FILEINFO_MIME_TYPE);
        $fileMime = finfo_file($fileInfo, $attachment);
        finfo_close($fileInfo);
        array_push($msgAttachment,'Content-Type:'.$fileMime.';name="'.$fileName.'"');
        array_push($msgAttachment,'Content-Transfer-Encoding:base64');
        array_push($msgAttachment,'Content-Disposition:attachment');
        $attached = file_get_contents($attachment);
        $attached = base64_encode($attached);
        $attached = chunk_split($attached);
        array_push($msgAttachment,$attached);
        
        return implode("r\n",$msgAttachment);
    }
    
    private function _prepAlternative() {
        $mode = 0;
        $msgContent = array();        

        if (!empty($this->_plainText)) $mode = 1;
        if (empty($this->_html)) $mode = 1; else $mode += 2;        
        
        array_push($msgContent,'--'.$this->_boundaryA);
        switch($mode) {
            case 1:
                array_push($msgContent,'Content-Type:text/plain;charset="'.$this->_charset.'"');
                array_push($msgContent,'Content-Transfer-Encoding:'.$this->_content_transfer_encoding);
                array_push($msgContent,"\r\n".wordwrap($this->_plainText));
                break;
            case 2:
                array_push($msgContent,'Content-Type:text/html;charset="'.$this->_charset.'"');
                array_push($msgContent,'Content-Transfer-Encoding:'.$this->_content_transfer_encoding);
                array_push($msgContent,"\r\n".wordwrap($this->_html));
                break;
            case 3:
                array_push($msgContent,'Content-Type:text/plain;charset="'.$this->_charset.'"');
                array_push($msgContent,'Content-Transfer-Encoding:'.$this->_content_transfer_encoding);
                array_push($msgContent,"\r\n".wordwrap($this->_plainText));
                array_push($msgContent,'--'.$this->_boundaryA);
                array_push($msgContent,'Content-Type:text/html;charset="'.$this->_charset.'"');
                array_push($msgContent,'Content-Transfer-Encoding:'.$this->_content_transfer_encoding);
                array_push($msgContent,"\r\n".wordwrap($this->_html));
        }
        array_push($msgContent,'--'.$this->_boundaryA.'--');
        return implode("\r\n",$msgContent);
    }
    
    private function _prepHeaders() {
        if (!empty($this->_from)) {
            $from = 'From:'.$this->_from;
            array_push($this->_headers,$from);
        }
        
        if (!empty($this->_replyTo)) {
            $replyTo = 'Reply-To:'.$this->_replyTo;
            array_push($this->_headers,$replyTo);
        }
        
        if (count($this->_cc) > 0) {
            $cc = 'Cc:'.implode(',',$this->_cc);
            array_push($this->_headers,$cc);
        }
        
        if (count($this->_bcc) > 0) {
            $bcc = 'Bcc:'.implode(',',$this->_bcc);
            array_push($this->_headers,$bcc);
        }
        
        if (!empty($this->_returnPath)) {
            $returnPath = 'Return-Path:'.$this->_returnPath;
            array_push($this->_headers,$returnPath);
        }
        
        if (!empty($this->_xMailer)) {
            $xMailer = 'X-Mailer:'.$this->_xMailer;
            array_push($this->_headers,$xMailer);
        }
        
        if (!empty($this->_xPriority)) {
            $priority = 'X-Priority:'.$this->_xPriority;
            array_push($this->_headers,$priority);
        }
        
        if (!empty($this->_mime)) {
            $from = 'MIME-Version:'.$this->_mime;
            array_push($this->_headers,$from);
        }
    }
}